/*
 *  e100_read.c
 *  
 *
 *  Created by Yingkai Hu on 12/3/11.
 *  Copyright 2011 NYU. All rights reserved.
 *
 */

#include "xinu.h"

/*------------------------------------------------------------------------
 * e100_read - read a packet from an E100 device
 *------------------------------------------------------------------------
 */

devcall e100_read(
	struct ether *ethptr,	/* ptr to entry in ethertab	*/
	void *buf,				/* buffer to hold packet	*/
	uint32 len)				/* length of buffer		*/
{
	struct	e100_rx_desc *descptr;	/* ptr to ring descriptor	*/
	char	*pktptr;				/* ptr used during packet copy	*/
	uint32	head;					/* head of ring buffer 		*/
	uint32	status;					/* status of entry		*/
	uint32	length;					/* packet length		*/
	int32 	retval;
	//uint32 	rdt;
	
	/* Wait for a packet to arrive */
	wait(ethptr->isem);
	
	/* Find out where to pick up the packet */
	
	head = ethptr->rxHead;
	descptr = (struct e100_rx_desc *)ethptr->rxRing + head;
	status = descptr->status;
	
	if (!(status & cb_ok)){		/* check for error */
		kprintf("e100_read: packet error!\n");
		retval = SYSERR;
	}else {						/* pick up the packet */			
		pktptr = (char *)(descptr->data);
		length = descptr->actual_count & 0x3FFF;
		memcpy(buf, pktptr, length);
		retval = length;
	}
	
	/* Clear up the descriptor and the buffer */
	
	descptr->status = 0;
	descptr->command = 0;
	//descptr->link = 0;
	descptr->reserved = 0;
	descptr->actual_count = 0;
	descptr->size = ETH_BUF_SIZE;
	memset((char *)(descptr->data), '\0', ETH_BUF_SIZE); 
	
	ethptr->rxHead = (ethptr->rxHead + 1) % ethptr->rxRingSize;
	
	return retval;

}
